package com.ptt.sqm.ws;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONObject;
import org.ksoap2.HeaderProperty;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.PropertyInfo;
import org.ksoap2.serialization.SoapObject;
import org.ksoap2.serialization.SoapPrimitive;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.ksoap2.transport.AndroidHttpTransport;

import com.ptt.sqm.model.ContactInfo;
import com.ptt.sqm.session.SessionManager;
import com.ptt.sqm.util.AppUtil;
import com.ptt.sqm.util.WidgetUtil;
import com.ptt.sqmonmobile.R;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.IntentSender.SendIntentException;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
import android.util.Log;
import android.view.Display;
import android.widget.Toast;

/**
 * @author AndroidExample DotNetWebService Class
 * 
 */
@SuppressLint("NewApi")
public class WebserviceCall implements IDefaulCall {

	private static WebserviceCall singleton;

	private String namespace;
	private String url;

	StringBuilder json;
	String SOAP_ACTION;
	SoapObject request = null, objMessages = null;
	SoapSerializationEnvelope envelope;
	AndroidHttpTransport androidHttpTransport;
	public AsyncResponse delegate = null;
	Context context;

	// Session Manager
	SessionManager session;

	public static WebserviceCall getInstance(String url, String namespace, SessionManager session, Context context) {
		if (singleton == null) {
			singleton = new WebserviceCall(url, namespace, session, context);
		}

		return singleton;
	}

	private WebserviceCall(String url, String namespace, SessionManager session, Context context) {
		this.url = url;
		this.namespace = namespace;
		this.session = session;
		this.context = context;
	}

	public static void reset() {
		singleton = null;
	}

	/**
	 * Set Envelope
	 */
	protected void SetEnvelope() {

		try {

			// Creating SOAP envelope
			envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);

			// You can comment that line if your web service is not .NET one.
			envelope.dotNet = true;

			envelope.setOutputSoapObject(request);
			androidHttpTransport = new AndroidHttpTransport(url);
			androidHttpTransport.debug = true;

		} catch (Exception e) {
			System.out.println("Soap Exception---->>>" + e.toString());
		}
	}

	/**
	 * Set Header
	 */
	private void SetHeader(List headerRequestList) {
		// TODO Auto-generated method stub
		Map user = session.getCookie();
		if (user != null && user.get(session.KEY_SETSESSION) != null) {
			HeaderProperty headerProperty = new HeaderProperty(session.KEY_SETSESSION, (String) user.get(session.KEY_SETSESSION));
			headerRequestList.add(headerProperty);
		} else {
			headerRequestList = null;
		}

	}

	public String execute(String MethodName, PropertyInfo... props) {

		try {
			SOAP_ACTION = namespace + "/" + MethodName;

			// Adding values to request object
			request = new SoapObject(namespace, MethodName);

			// Adding String value to request object
			for (PropertyInfo prop : props) {
				if (prop != null)
					if (!prop.getType().equals(SoapObject.class))
						request.addProperty(prop);
					else
						request.addSoapObject((SoapObject) prop.getValue());
			}

			SetEnvelope();

			try {
				List headerRequestList = new ArrayList();
				SetHeader(headerRequestList);

				// if(!WidgetUtil.isNetworkAvailable(context)) {
				// session.logoutUserWithError();
				// return null;
				// }

				// SOAP calling webservice
				List headerResponseList = androidHttpTransport.call(SOAP_ACTION, envelope, headerRequestList);

				
				if(MethodName.equals("WS_SaveContacts") || MethodName.equals("WS_DeleteContactImage") || MethodName.equals("WS_SaveSupports") || MethodName.equals("WS_SaveEquipmentsSQM") || MethodName.equals("WS_SaveBusinessSupportsSQM")) {
					SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
					WidgetUtil.writeToFile(MethodName + AppUtil.UNDER_SCROLL + dateFormat.format(new Date()) + ".xml", androidHttpTransport.requestDump);
				}
				
				
				for (Object header : headerResponseList) {
					HeaderProperty headerProperty = (HeaderProperty) header;
					if (headerProperty.getKey() != null && headerProperty.getKey().equals(session.KEY_GETSESSION)) {
						session.createCookie(headerProperty.getValue());
					}
				}

				// Got Webservice response
				SoapObject response = (SoapObject) envelope.bodyIn;
				json = new StringBuilder();
				recursive(response, true);

				return json.toString();

			} catch (NullPointerException npe) {
				Log.i("webservice", npe.toString());
				session.logoutUserWithError();
				return null;
			} catch (UnknownHostException uhe) {
				Log.i("webservice", uhe.toString());
				session.logoutUserWithError();
				return null;
			} catch (Exception e) {
				// TODO: handle exception
				Log.i("webservice", e.toString());
				session.logoutUserWithError();

				return null;
			}
		} catch (Exception e) {
			// TODO: handle exception
			Log.i("WebserviceCall", e.toString());
			return null;
		}

	}

	public String recursive(SoapObject response, boolean isRoot) {
		// Inside your for loop
		String complexType = "";
		for (int i = 0; i < response.getPropertyCount(); i++) {
			if (response.getProperty(i) instanceof SoapObject) {
				// Add ComplexType
				PropertyInfo prop = new PropertyInfo();
				response.getPropertyInfo(i, prop);
				if (((SoapObject) prop.getValue()).getPropertyCount() == 0) {
					// No Value
					json.append(AppUtil.DOUBLE_QUOTE);
					json.append(prop.getName());
					json.append(AppUtil.DOUBLE_QUOTE);
					json.append(AppUtil.COLON);
					json.append(AppUtil.DOUBLE_QUOTE);
					json.append(AppUtil.DOUBLE_QUOTE);
				} else {
					if (!complexType.equals(prop.getName())) {
						if (!isRoot) {
							json.append(AppUtil.DOUBLE_QUOTE);
							json.append(prop.getName());
							json.append(AppUtil.DOUBLE_QUOTE);
							json.append(AppUtil.COLON);
							json.append(AppUtil.COMPLEX_OPEN);
						}
						json.append(AppUtil.NESTED_OPEN);
					} else {
						json.append(AppUtil.NESTED_OPEN);
					}

					String check = recursive((SoapObject) response.getProperty(i), false);

					if (i == response.getPropertyCount() - 1) {
						json.append(AppUtil.NESTED_CLOSE);
						if (!isRoot) {
							json.append(AppUtil.COMPLEX_CLOSE);
						}
					} else if (complexType.length() != 0 && !complexType.equals(prop.getName())) {
						json.append(AppUtil.NESTED_CLOSE);
						if (!isRoot) {
							json.append(AppUtil.COMPLEX_CLOSE);
						}
					} else if (complexType.length() == 0) {
						PropertyInfo nextProp = new PropertyInfo();
						response.getPropertyInfo(i + 1, nextProp);
						if (!prop.getName().equals(nextProp.getName())) {
							json.append(AppUtil.NESTED_CLOSE);
							if (!isRoot) {
								json.append(AppUtil.COMPLEX_CLOSE);
							}
						} else
							json.append(AppUtil.NESTED_CLOSE);
					} else {
						json.append(AppUtil.NESTED_CLOSE);
					}

					complexType = prop.getName();
				}
			} else {
				// Add Attribute
				PropertyInfo prop = new PropertyInfo();
				response.getPropertyInfo(i, prop);
				json.append(AppUtil.DOUBLE_QUOTE);
				json.append(prop.getName());
				json.append(AppUtil.DOUBLE_QUOTE);
				json.append(AppUtil.COLON);
				json.append(AppUtil.DOUBLE_QUOTE);
				json.append(prop.getValue());
				json.append(AppUtil.DOUBLE_QUOTE);
			}

			// Add Comma
			if (i < response.getPropertyCount() - 1) {
				json.append(AppUtil.COMMA);
			}
		}
		return complexType;
	}

}
